#pragma once
#include <iostream>
#include "log_pro.hpp"
#include <jsoncpp/json/json.h>

// #define MYPROTOCOL 1

char blank_space_sep = ' ';
char massgae_sep = '\n';

bool encap(std::string &data)
{
    std::string massage(std::to_string(data.size()));//构造函数
    massage += massgae_sep;
    massage += data;
    massage += massgae_sep;
    data = massage;
    return true;
}

bool unpack(std::string &massage, std::string &data)
{
    int pos = massage.find(massgae_sep);
    if (pos == std::string::npos)
        return false;
    // 先获取出报文的长度
    std::string str_len = massage.substr(0, pos);

    int len = std::atoi(str_len.c_str()); // 这里如果把atoi换成stoi就会出现和蛋哥一样的问题

    // 通过检验报文长度是否正确来证明报文发送是否成功
    int total_len = len + str_len.size() + 2;
    if (total_len > massage.size()) // 如果我们解析出来的len要大于masage的长度的话，说明这个massage不全我们无法处理，
        return false;               // 但即使是我们的len小于massage也有可能会出现无法处理massage的情况，所以我们客户端
                                    // 发送的数据需要被协议规定好发送，这样久不会出现len小于massage还无法处理的情况
    // 通过获取的报文长度获取报文
    data = massage.substr(pos + 1, len);

    // 还有与网络交互的移除功能没写
    massage.erase(0, total_len);

    return true;
}

class request
{
public:
    request(int x, char op, int y)
        : _x(x), _y(y), _op(op)
    {
    }
    request()
    {
    }
    ~request()
    {
    }
    bool serialize(std::string &data)
    {
#ifdef MYPROTOCOL
        data = std::to_string(_x);
        data += blank_space_sep;
        data += _op;
        data += blank_space_sep;
        data += std::to_string(_y);
        return true;
#else
        Json::Value massage;
        massage["x"] = _x;
        massage["op"] = _op;
        massage["y"] = _y;
        Json::FastWriter w;
        data = w.write(massage);
        return true;

#endif
    }
    bool deserialize(const std::string &str)
    {
#ifdef MYPROTOCOL
        // 先找到第一个空格的位置，找出左操作数
        int pos = str.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;
        std::string leftData = str.substr(0, pos);

        // 再从pos位置后开始找第一个空格的位置，找出右操作数
        pos = str.find(blank_space_sep, pos + 1);
        if (pos == std::string::npos)
            return false;
        std::string rightData = str.substr(pos + 1);

        // 最后通过左右空格找出操作符
        if (str[pos] != str[pos - 2])
            return false;
        _op = str[pos - 1];

        _x = std::atoi(leftData.c_str());
        _y = std::atoi(rightData.c_str());
        return true;
#else
        Json::Value data;
        Json::Reader r;
        r.parse(str, data);
        _x = data["x"].asInt();
        _y = data["y"].asInt();
        _op = data["op"].asInt();

        return true;
#endif
    }

    void CreateQeq()
    {
        std::cout << "获取一个请求:" << std::endl;
        std::cout << _x << _op << _y << "=?" << std::endl;
        std::cout << "#################################" << std::endl;
    }

public:
    int _x;
    int _y;
    char _op;
};

class response
{
public:
    bool serialize(std::string &data)
    {
#ifdef MYPROTOCOL

        data += std::to_string(_result);
        data += blank_space_sep;
        data += std::to_string(_code);
        return true;
#else
        Json::Value massage;
        massage["result"] = _result;
        massage["code"] = _code;
        Json::FastWriter w;
        data = w.write(massage);
        return true;

#endif
    }
    bool deserialize(const std::string str)
    {
#ifdef MYPROTOCOL
        // 找到第一个空格的位置，分割出两个成员
        int pos = str.find(blank_space_sep);
        if (pos == std::string::npos)
            return false;
        std::string leftData = str.substr(0, pos);
        _result = std::atoi(leftData.c_str());
        std::string rightData = str.substr(pos + 1);
        _code = std::atoi(rightData.c_str());
        return true;
#else
        Json::Value data;
        Json::Reader r;
        r.parse(str, data);
        _result = data["result"].asInt();
        _code = data["code"].asInt();

        return true;

#endif
    }

    void getRes()
    {
        std::cout << "获取一个响应:" << std::endl;
        std::cout << "result:" << _result << " code:" << _code << std::endl;
        std::cout << "#################################" << std::endl;
    }

    response(int result = 0, int code = 0)
        : _result(result), _code(code)
    {
    }
    ~response()
    {
    }

public:
    int _result;
    int _code;
};
